<?php

namespace App\Service\Office;

use Exception;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Writer\HTML\Element\Container;
use Ramsey\Uuid\Uuid;
use Storage;

class WordService
{
    public string $imgPath = '';

    /**
     * docx转html
     * @param $path
     * @return string
     * @throws \PhpOffice\PhpWord\Exception\Exception
     * @throws Exception
     */
    public function docx2html($path): string
    {
        if (!file_exists($path)) throw new Exception('文件不存在');

        $filename = basename($path);
        $htmlFilename = str_replace('.docx', '', $filename);
        $htmlFilePath = storage_path('app/import/docx2html/' . $htmlFilename . '.html');

        $docx = IOFactory::load($path);
        $writer = IOFactory::createWriter($docx, 'HTML');
        $html = '';
        $stylePreg = '/(<[^>]+) style=".*?"/i';
        if (empty($docx->getSections())) throw new Exception('文档无法解析');
        foreach ($docx->getSections() as $section) {
            $writer = new Container($writer, $section);
            $_html = $writer->write();
            $html .= preg_replace($stylePreg, '$1', $_html);
        }

        // 移除每个 <p> 标签中的所有 <span> 标签
        $html = preg_replace('/<p>(.*?)<\/p>/isu', '<p>$1</p>', $html);
        $html = preg_replace('/<span[^>]*>(.*?)<\/span>/isu', '$1', $html);
        // 图片处理
        $html = $this->htmlImgUpload($html);

        // 将字符串数据写入文件中
        //if (file_put_contents($htmlFilePath, $html) === false) {
        //    throw new Exception('导入失败');
        //}
        if(Storage::put($htmlFilePath, $html, 'local') === false) {
            throw new Exception('导入失败');
        }

        return $html;
    }

    /**
     * html中base64图片处理
     * @param $html
     * @return array|mixed|string|string[]
     * @throws Exception
     */
    public function htmlImgUpload($html) {
        $regex = '/<img[^>]+src=("|\')data:image\/[^;]+;base64,([^"\']+)("|\')[^>]*>/i';

        // 匹配所有满足条件的标签并替换其中的属性值
        preg_match_all($regex, $html, $matches);
        foreach ($matches[0] as $match) {
            // 提取图片数据的 base64 编码部分
            preg_match('/data:image\/[^;]+;base64,([^"\']+)/i', $match, $base64);
            if (!empty($base64[1])) {
                // 上传图片
                $_imgName = Uuid::uuid4()->getHex().'.png';
                $_imgData = base64_decode($base64[1]);
                if (empty($this->imgPath)) {
                    $this->imgPath = '/';
                }else {
                    if (substr($this->imgPath, -1) !== '/') {
                        // 如果最后一个字符不是/，则在末尾添加/
                        $this->imgPath = rtrim($this->imgPath, '/') . '/';
                    }
                    if (substr($this->imgPath, 0, 1) === '/') {
                        // 如果第一个字符是/，则删除首部/
                        $this->imgPath = ltrim($this->imgPath, '/');
                    }
                }
                $_imgPath = $this->imgPath.$_imgName;
                // 图片上传
                $ossResult = Storage::disk("aliyun")->put($_imgPath, $_imgData);
                if (!$ossResult) {
                    throw new Exception('图片上传服务异常');
                }
                $newMatch = preg_replace('/src=("|\')data:image\/[^;]+;base64,([^"\']+)("|\')/i', 'src="' . '/'.$_imgPath . '"', $match);
                $html = str_replace($match, $newMatch, $html);
            }
        }

        // 输出处理后的 HTML 内容
        return $html;
    }


    /**
     * 返回处理完的题目数组
     * @param $html
     * @param $courseId
     * @return array
     */
    public function htmlHandle($html, $courseId): array
    {
        $questions = [];

        $html = str_replace("\n", '[LINE]', $html);
        $htmlLines = explode("[LINE]", $html);
        $lines = [];
        // 合并段落
        $mergeLineStart = false;
        foreach($htmlLines as $key => $line) {
            $line = trim(strip_tags($line, '<img><table><tr><td><tbody>'));
            $linesLastIndex = count($lines) -1;

            if (!empty(trim($line))) {
                // 判断是否为首行
                if (preg_match('/^【\p{Han}{2,5}】/u', mb_substr($line, 0, 8))) {
                    $_line = $line;

                    if(mb_substr($line, 0, 4) == '【结束】' || mb_substr($line, 0, 6) == '【小题结束】')  $mergeLineStart = false;
                    else $mergeLineStart = true;

                    $lines[] = $_line;
                }
                // 如果不是第一行
                else {
                    // 合并到其一行
                    if ($mergeLineStart && count($lines) > 0) {
                        $_line = preg_match('/^【\p{Han}{2,5}】/u', mb_substr($lines[$linesLastIndex], 0, 8)) ? (!empty(mb_substr($lines[$linesLastIndex], 4)) ? '<br>'.$line : $line) : $line;
                        $lines[$linesLastIndex] .= $_line;
                    }
                }
            }
        }

        $tmpQuestion = [];
        $tmpQuestionChildrenCurrentIndex = 0;   // 当前大题的小题索引值

        $questionInit = [
            'title' => '',
            'options' => null,
            'questionType' => null,
            'answer' => null,
            'knowledge' => null,
            'anylysis' => null, // 分析
            'analysis' => null, // 解析
            'difficulty' => 0,
            'difficultyValue' => 0,
        ];

        foreach($lines as $line) {
            $line = str_replace('<tr><br>', '<tr>', $line);
            $line = str_replace('<br><tr>', '<tr>', $line);
            $line = str_replace('<td><br>', '<td>', $line);
            $line = str_replace('<br><td>', '<td>', $line);
            $line = str_replace('</tr><br>', '</tr>', $line);
            $line = str_replace('<br></tr>', '</tr>', $line);
            $line = str_replace('</td><br>', '</td>', $line);
            $line = str_replace('<br></td>', '</td>', $line);

            // 可以入值的题目数组元素下标
            $questionsCurrentIndex = count($questions);

            if (mb_substr($line, 0, 4) == '【题干】') {
                $tmpQuestion = $questionInit;
                $tmpQuestion['children'] = [];
                $tmpQuestion['title'] = trim(mb_substr($line, 4));
            }
            elseif (mb_substr($line, 0, 4) == '【选项】') {
                $tmpQuestion['options'] = str_replace('<br>', '|NTK|', trim(mb_substr($line, 4)));
            }
            elseif (mb_substr($line, 0, 4) == '【题型】') {
                $tmpQuestion['questionType'] = trim(mb_substr($line, 4));
            }
            elseif (mb_substr($line, 0, 4) == '【答案】') {
                $tmpQuestion['answer'] = trim(mb_substr($line, 4));
            }
            elseif (mb_substr($line, 0, 5) == '【知识点】') {
                $tmpQuestion['knowledge'] = trim(mb_substr($line, 5));
            }
            elseif (mb_substr($line, 0, 4) == '【分析】') {
                $tmpQuestion['anylysis'] = trim(mb_substr($line, 4));
            }
            elseif (mb_substr($line, 0, 4) == '【解析】') {
                $tmpQuestion['analysis'] = trim(mb_substr($line, 4));
            }
            elseif (mb_substr($line, 0, 4) == '【难度】') {
                $tmpQuestion['difficultyValue'] = trim(mb_substr($line, 4));
                $tmpQuestion['difficulty'] = mb_substr($line, 4) <= 0.3 ? 0 : (mb_substr($line, 4) <= 0.6 ? 1 : 2); // 难度,012易中难
            }
            // 小题
            elseif (mb_substr($line, 0, 6) == '【小题题干】') {
                $tmpQuestionChildrenCurrentIndex = count(!empty($tmpQuestion['children']) ? $tmpQuestion['children'] : []);
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex] = $questionInit;
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['title'] = trim(mb_substr($line, 6));
            }
            elseif (mb_substr($line, 0, 6) == '【小题选项】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['options'] = str_replace('<br>', '|NTK|', trim(mb_substr($line, 6)));
            }
            elseif (mb_substr($line, 0, 6) == '【小题题型】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['questionType'] = trim(mb_substr($line, 6));
            }
            elseif (mb_substr($line, 0, 6) == '【小题答案】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['answer'] = trim(mb_substr($line, 6));
            }
            //elseif (mb_substr($line, 0, 7) == '【小题知识点】') {
            //    $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['knowledge'] = mb_substr($line, 6);
            //}
            elseif (mb_substr($line, 0, 6) == '【小题分析】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['anylysis'] = trim(mb_substr($line, 6));
            }
            elseif (mb_substr($line, 0, 6) == '【小题解析】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['analysis'] = trim(mb_substr($line, 6));
            }
            elseif (mb_substr($line, 0, 6) == '【小题难度】') {
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['difficultyValue'] = trim(mb_substr($line, 6));
                $tmpQuestion['children'][$tmpQuestionChildrenCurrentIndex]['difficulty'] = mb_substr($line, 6) <= 0.3 ? 0 : (mb_substr($line, 6) <= 0.6 ? 1 : 2); // 难度,012易中难
            }
            elseif (mb_substr($line, 0, 6) == '【小题结束】') {
                $tmpQuestionChildrenCurrentIndex = 0;
            }
            elseif (mb_substr($line, 0, 4) == '【结束】') {
                if (!empty($tmpQuestion)) $questions[$questionsCurrentIndex] = $tmpQuestion;
                $tmpQuestion = [];
            }
        }
        return $questions;
    }
}
